package com.enation.app.javashop.buyer.api.member;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.enation.app.javashop.core.base.message.MemberRegisterMsg;
import com.enation.app.javashop.core.client.member.MemberCouponClient;
import com.enation.app.javashop.core.distribution.model.dos.DistributionDO;
import com.enation.app.javashop.core.distribution.service.DistributionManager;
import com.enation.app.javashop.core.member.model.dos.ConnectDO;
import com.enation.app.javashop.core.member.model.dos.Member;
import com.enation.app.javashop.core.member.model.dos.MemberCoupon;
import com.enation.app.javashop.core.member.model.enums.ConnectTypeEnum;
import com.enation.app.javashop.core.member.model.vo.MemberInviterVO;
import com.enation.app.javashop.core.member.model.dto.MemberCouponQueryParam;
import com.enation.app.javashop.core.member.model.enums.LoginStatusEnums;
import com.enation.app.javashop.core.member.model.vo.MemberCouponNumVO;
import com.enation.app.javashop.core.member.service.ConnectManager;
import com.enation.app.javashop.core.member.service.MemberCouponManager;
import com.enation.app.javashop.core.member.service.MemberManager;
import com.enation.app.javashop.core.promotion.coupon.model.dos.CouponDO;
import com.enation.app.javashop.core.promotion.coupon.model.dos.CouponTypeEnum;
import com.enation.app.javashop.core.promotion.coupon.service.CouponManager;
import com.enation.app.javashop.core.shop.service.ShopManager;
import com.enation.app.javashop.framework.context.ThreadContextHolder;
import com.enation.app.javashop.framework.context.UserContext;
import com.enation.app.javashop.framework.database.Page;
import com.enation.app.javashop.framework.security.model.Buyer;
import com.enation.app.javashop.framework.util.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 会员优惠券
 *
 * @author Snow create in 2018/6/13
 * @version v2.0
 * @since v7.0.0
 */
@RestController
@RequestMapping("/members/coupon")
@Api(description = "会员优惠券相关API")
@Validated
public class MemberCouponBuyerController {

    @Autowired
    private MemberCouponManager memberCouponManager;

    @Autowired
    private MemberCouponClient memberCouponClient;
    @Autowired
    private CouponManager couponManager;
    @Autowired
    private ShopManager shopManager;
    @Autowired
    private MemberManager memberManager;
    @Autowired
    private DistributionManager distributionManager;
    @Autowired
    private ConnectManager connectManager;

    protected final Log logger = LogFactory.getLog(this.getClass());

    @ApiOperation(value = "查询我的优惠券列表", response = MemberCoupon.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "status", value = "优惠券状态 0为全部，1为未使用且可用，2为已使用，3为已过期, 4为不可用优惠券（已使用和已过期）", dataType = "int", paramType = "query", allowableValues = "0,1,2,3,4"),
            @ApiImplicitParam(name = "page_no", value = "页数", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "page_size", value = "条数", dataType = "int", paramType = "query"),
    })
    @GetMapping
    public Page<MemberCoupon> list(@ApiIgnore Integer status, @ApiIgnore Integer pageNo, @ApiIgnore Integer pageSize) {
        MemberCouponQueryParam param = new MemberCouponQueryParam();
        param.setStatus(status);
        param.setPageNo(pageNo);
        param.setPageSize(pageSize);
        return this.memberCouponManager.list(param);
    }


    @ApiOperation(value = "用户领取优惠券")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "coupon_id", value = "优惠券id", required = true, dataType = "int", paramType = "path")
    })
    @PostMapping(value = "/{coupon_id}/receive")
    public String receiveBonus(@ApiIgnore @PathVariable("coupon_id") Integer couponId) {
        //限领检测
        this.memberCouponManager.checkLimitNum(couponId);
        Buyer buyer = UserContext.getBuyer();
        this.memberCouponClient.receiveBonus(buyer.getUid(), couponId);
        return "";
    }

    @ApiOperation(value = "用户领取订单分享优惠券")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "order_sn", value = "订单号", required = true, dataType = "String", paramType = "path"),
            @ApiImplicitParam(name = "coupon_id", value = "优惠券id", required = true, dataType = "int", paramType = "path")
    })
    @PostMapping(value = "/shareCoupon/{order_sn}/{coupon_id}")
    public MemberCoupon shareCoupon(@ApiIgnore @PathVariable("order_sn") String orderSn,@ApiIgnore @PathVariable("coupon_id") Integer couponId) {
        //限领检测
        this.memberCouponManager.checkLimitNum(couponId);
        Buyer buyer = UserContext.getBuyer();
        MemberCoupon memberCoupon = new MemberCoupon(buyer.getUid(), couponId);
        memberCoupon.setReceiveOrder(orderSn);
        this.memberCouponManager.receiveBonus(memberCoupon);
        return memberCoupon;
    }


    @ApiOperation(value = "结算页—读取可用的优惠券列表", response = MemberCoupon.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "seller_ids", value = "商家ID集合", required = true, dataType = "int", paramType = "path", allowMultiple = true),
    })
    @GetMapping("/{seller_ids}")
    public List<MemberCoupon> listByCheckout(@ApiIgnore @PathVariable("seller_ids") @NotNull(message = "商家ID不能为空") Integer[] sellerIds) {
        return this.memberCouponManager.listByCheckout(sellerIds[0], UserContext.getBuyer().getUid());
    }


    @ApiOperation(value = "优惠券—未使用,已使用,已过期状态总数量")
    @GetMapping("/num")
    public MemberCouponNumVO getStatusNum() {
        return this.memberCouponManager.statusNum();
    }



    @GetMapping("/receive_volume")
    @ApiOperation(value = "领取优惠券(新人券/首单券)返回信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "user_type", value = "用户类型", required = true, dataType = "int", paramType = "path"),
            @ApiImplicitParam(name = "city", value = "城市", required = true, dataType = "String", paramType = "path")
    })
    public Map<String,Object> receiveVolume(@ApiIgnore Integer userType,@ApiIgnore String city){
        Map<String,Object> map = new HashMap<>();
        map.put("success",false);
        try {
            Integer buyerId = UserContext.getBuyer().getUid();
            DistributionDO distributionDO = distributionManager.getDistributorByMemberId(buyerId);
            Integer visitChannel = -1;
            // 通过推广领券 注册 不发新人券
            if(distributionDO != null ){
                visitChannel = distributionDO.getVisitChannel();
            }
            // 根据用户所在城市定位店铺优惠券
            Integer sellerId=null;
            Integer shopId = shopManager.getShopByCity(city);
            if(shopId!=null && shopId!=0){
                sellerId=shopId;
            }

            // 初始化
            MemberCoupon memberCoupon = null;
            // 1.1.1 当前登录人为未注册的新人
            if(userType == LoginStatusEnums.NEW_USERS.getIndex()){
                // 1.2.2 查询登录人 新人券的有效时间
                String[] couponType = {CouponTypeEnum.NEW_REG.value()};
                memberCoupon = memberCouponManager.getNewCoupon(buyerId,sellerId,couponType);
                // 查询没有领过券 重新发券  解决切换城市发券
                if(memberCoupon == null && (visitChannel == null || visitChannel != 6)){
                    Member member = memberManager.getModel(buyerId);
                    // 给用户发放新人券
                    MemberRegisterMsg memberRegisterMsg = new MemberRegisterMsg();
                    memberRegisterMsg.setMember(member);
                    memberRegisterMsg.setUuid(ThreadContextHolder.getHttpRequest().getHeader("uuid"));
                    couponManager.memberRegister(memberRegisterMsg,0,city);
                    // 1.3.2 查询登录人 新人券的有效时间
                    memberCoupon = memberCouponManager.getNewCoupon(buyerId,sellerId,couponType);
                }

                // 1.3 当前登录人为 首单用户
            }else if(userType== LoginStatusEnums.FIRST_ORDER_USERS.getIndex()){
                String[] couponType = {CouponTypeEnum.FIRST_ORDER.value()};
                // 1.3.2 查询登录人 首单券的有效时间
                memberCoupon = memberCouponManager.getNewCoupon(buyerId,sellerId,couponType);
                // 没有领过券 重新发券  解决切换城市发券
                if(memberCoupon == null){
                    Member member = memberManager.getModel(buyerId);
                    // 给用户发放首单券
                    MemberRegisterMsg memberRegisterMsg = new MemberRegisterMsg();
                    memberRegisterMsg.setMember(member);
                    couponManager.memberRegister(memberRegisterMsg,1,city);
                    // 1.3.2 查询登录人 首单券的有效时间
                    memberCoupon = memberCouponManager.getNewCoupon(buyerId,sellerId,couponType);
                }

            }
            if(memberCoupon != null){
                map.put("success",true);
                // 优惠券面额
                map.put("coupon_price",memberCoupon.getCouponPrice());
                // 优惠券门槛金额
                map.put("coupon_threshold_price",memberCoupon.getCouponThresholdPrice());
                map.put("start_time", DateUtil.toString(memberCoupon.getStartTime(),"yyyy-MM-dd"));
                map.put("end_time", DateUtil.toString(memberCoupon.getEndTime(),"yyyy-MM-dd"));
            }
            return map;
        }catch (Exception e){
            logger.error("领取优惠券(新人券/首单券)返回信息错误:"+e);
        }
        return map;
    }

    /**
     * 推荐领券
     */
    @PostMapping("/recommended_coupons")
    @ApiOperation(value = "推荐领券我的邀请人列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "member_id", value = "会员id", required = true, dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "page_no", value = "页码", required = true, paramType = "query", dataType = "int"),
            @ApiImplicitParam(name = "page_size", value = "分页大小", required = true, paramType = "query", dataType = "int"),

    })
    public Page recommendedCoupons(@ApiIgnore Integer memberId,@ApiIgnore Integer pageNo, @ApiIgnore Integer pageSize){
        // 推荐领奖页面信息
        String recommendedCouponsVal = DictUtils.getDictValue("", "推荐领券", "RECOMMENDED_COUPONS");

        if(StringUtil.isEmpty(recommendedCouponsVal)){
            logger.error("请在数据字典中配置RECOMMENDED_COUPONS的值");
            return new Page();
        }
        JSONObject json = JSON.parseObject(recommendedCouponsVal);
        String startTime = json.getString("startTime");
        String endTime = json.getString("endTime");

        long startTimeTimeLong = 0;
        if(StringUtil.isEmpty(startTime)){
            return new Page();
        }else {
            // 活动开始时间大于当前时间  活动还没有开始
            startTimeTimeLong = DateUtil.getDateline(startTime, "yyyy-MM-dd HH:mm:ss");
            if(startTimeTimeLong > DateUtil.getDateline()){
                return new Page();
            }
        }
        long endTimeLong = 0;
        if(StringUtil.notEmpty(endTime)){
            // 活动结束时间 小于当前时间 活动已经结束
            endTimeLong = DateUtil.getDateline(endTime, "yyyy-MM-dd HH:mm:ss");
            if(endTimeLong < DateUtil.getDateline()){
                return new Page();
            }
        }
        // 我的邀请记录
        return distributionManager.getInviterList(memberId, startTimeTimeLong, endTimeLong, pageNo, pageSize);
    }

    /**
     * 推荐领券
     */
    @PostMapping("/recommended_coupons_ranking")
    @ApiOperation(value = "推荐领券排行榜")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page_no", value = "页码", required = true, paramType = "query", dataType = "int"),
            @ApiImplicitParam(name = "page_size", value = "分页大小", required = true, paramType = "query", dataType = "int"),

    })
    public Page recommendedCouponsRanking(@ApiIgnore Integer pageNo, @ApiIgnore Integer pageSize){
        // 页面数据
        String recommendedCouponsVal = DictUtils.getDictValue("", "推荐领券", "RECOMMENDED_COUPONS");
        if(StringUtil.isEmpty(recommendedCouponsVal)){
            logger.error("请在数据字典中配置RECOMMENDED_COUPONS的值");
            return new Page();
        }
        JSONObject json = JSON.parseObject(recommendedCouponsVal);
        String startTime = json.getString("startTime");
        String endTime = json.getString("endTime");
        long startTimeTimeLong = 0;
        if(StringUtil.isEmpty(startTime)){
            return new Page();
        }else {
            // 活动开始时间大于当前时间 活动还没有开始
            startTimeTimeLong = DateUtil.getDateline(startTime, "yyyy-MM-dd HH:mm:ss");
            if(startTimeTimeLong > DateUtil.getDateline()){
                return new Page();
            }
        }

        long endTimeLong = 0;
        if(StringUtil.notEmpty(endTime)){
            // 活动结束时间 小于当前时间 活动已经结束
            endTimeLong = DateUtil.getDateline(endTime, "yyyy-MM-dd HH:mm:ss");
            if(endTimeLong < DateUtil.getDateline()){
                return new Page();
            }
        }

        // 查看邀请人的到的钱
        JSONArray typeValye = json.getJSONArray("typeValye");
        Integer myFriendsRegisterReward = 0;
        if(!CollectionUtils.isEmpty(typeValye)){
            JSONObject jsonObject = JSON.parseObject(typeValye.getString(0));
            myFriendsRegisterReward = jsonObject.getInteger("myFriendsRegisterReward");
        }


        // 邀请的排行榜
        Page recommendedCouponsRanking = distributionManager.getRecommendedCouponsRanking(startTimeTimeLong,endTimeLong,pageNo, pageSize);
        List<MemberInviterVO> memberInviterVOList = recommendedCouponsRanking.getData();
        for (MemberInviterVO memberInviterVO : memberInviterVOList) {
            // 计算获取的钱数
            Integer inviterNum = memberInviterVO.getInviterNum();
            Double reward = CurrencyUtil.mul(Double.valueOf(myFriendsRegisterReward), Double.valueOf(inviterNum));
            memberInviterVO.setReward(reward);
        }
        return recommendedCouponsRanking;
    }

    /**
     * 落地页 '领' 字的标识
     */
    @GetMapping("/collarFlag")
    @ApiOperation(value = "落地页 '领' 字的标识")
    public int collarFlag(@RequestParam(value = "openId")String openId){
        // -1 什么都不显示 1 没有注册过
        int flag = -1;
        String recommendedCouponsVal = DictUtils.getDictValue("", "推荐领券", "RECOMMENDED_COUPONS");
        if(StringUtil.isEmpty(recommendedCouponsVal)){
            logger.debug("落地页'领'标识 没有配置RECOMMENDED_COUPONS");
            return flag;
        }
        JSONObject json = JSON.parseObject(recommendedCouponsVal);
        String startTime = json.getString("startTime");
        String endTime = json.getString("endTime");
        if(StringUtil.isEmpty(startTime)){
            return flag;
        }else {
            // 活动开始时间大于当前时间  活动还没有开始
            long startTimeTimeLong = DateUtil.getDateline(startTime, "yyyy-MM-dd HH:mm:ss");
            if(startTimeTimeLong > DateUtil.getDateline()){
                return flag;
            }
        }
        if(StringUtil.notEmpty(endTime)){
            // 活动结束时间 小于当前时间 活动已经结束
            long endTimeLong = DateUtil.getDateline(endTime, "yyyy-MM-dd HH:mm:ss");
            if(endTimeLong < DateUtil.getDateline()){
                return flag;
            }
        }
        // 查看被邀请人优惠券的发放量
        JSONArray friendsCouponIds = json.getJSONArray("friendsCouponIds");
        if(CollectionUtils.isEmpty(friendsCouponIds)){
            logger.error("请配置被邀请人优惠券id");
            return flag;
        }
        List<Integer> friendsCouponIdList = friendsCouponIds.toJavaList(Integer.class);
        List<CouponDO> couponDOList = couponManager.getByIds(friendsCouponIdList);
        if(CollectionUtils.isEmpty(couponDOList) || friendsCouponIdList.size() > couponDOList.size()){
            logger.error("请配置被邀请人优惠券");
            return flag;
        }
        boolean couponFlag = false;
        for (CouponDO couponDO : couponDOList) {
            if(couponDO.getCreateNum() <= couponDO.getReceivedNum()){
                couponFlag = true;
                break;
            }
        }
        if(couponFlag){
            return flag;
        }

        // 查看有没有注册过
        if(StringUtil.isEmpty(openId)){
            return flag;
        }
        // 查看优惠券的个数

        // 查询是否注册
        ConnectDO connectDO = connectManager.getConnect(openId, ConnectTypeEnum.WECHAT.value());
        if(connectDO == null){
            flag = 1;
        }
        return flag;
    }

    /**
     * 推广领券回显
     */
    @GetMapping("/recommendedCouponsEcho")
    @ApiOperation(value = "推广领券回显 ")
    public List recommendedCouponsEcho(){
        // -1 什么都不显示 1 没有注册过
        Integer buyerId = UserContext.getBuyer().getUid();
        String recommendedCouponsVal = DictUtils.getDictValue("", "推荐领券", "RECOMMENDED_COUPONS");
        if(StringUtil.isEmpty(recommendedCouponsVal)){
            logger.error("请在数据字典中配置RECOMMENDED_COUPONS的值");
        }
        JSONObject json = JSON.parseObject(recommendedCouponsVal);
        JSONArray friendsCouponIds = json.getJSONArray("friendsCouponIds");
        List<MemberCoupon> memberCouponList = null;
        if(!CollectionUtils.isEmpty(friendsCouponIds)){
            List<Integer> friendsCouponIdList = friendsCouponIds.toJavaList(Integer.class);
            Integer[] couponIds = new Integer[friendsCouponIdList.size()];
            friendsCouponIdList.toArray(couponIds);
            memberCouponList = memberCouponManager.getMemberCoupon(buyerId, couponIds);
        }
        // 封装数据
        List list = new ArrayList();
        if(!CollectionUtils.isEmpty(memberCouponList)){
            for (MemberCoupon memberCoupon : memberCouponList) {
                Map<String,Object> memberCouponMap = new HashMap<>();
                // 优惠券面额
                memberCouponMap.put("coupon_price",memberCoupon.getCouponPrice());
                // 优惠券门槛金额
                memberCouponMap.put("coupon_threshold_price",memberCoupon.getCouponThresholdPrice());
                memberCouponMap.put("start_time", DateUtil.toString(memberCoupon.getStartTime(),"yyyy.MM.dd"));
                memberCouponMap.put("end_time", DateUtil.toString(memberCoupon.getEndTime(),"yyyy.MM.dd"));
                list.add(memberCouponMap);
            }
        }
        return list;
    }

}
